package com.jiliang.common.utils;

import com.jiliang.common.exception.Errors;
import com.jiliang.common.exception.business.ServerServiceException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.UUID;

@Log4j2
@Component
public class JWTUtils {
    private static final String secret = "5ISMOdJ1nNTe2ly7X13oXquyeGuuLkeyLTYpLWwUsCWwoYmgYFbFQKNs2475Bw8E";
    private static final SecretKey priKey = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));

    /**
     * Token生成
     * @param boId 用户Id
     * @param expireTime 过期时间
     * @param chronoUnit 时间单位
     * @return Token令牌
     */
    public static String generateToken(String boId, Long expireTime, ChronoUnit chronoUnit) {
        return Jwts.builder()
                .issuer("新区一体化门户")
                .subject(boId)
                .issuedAt(new Date())
                .id(UUID.randomUUID().toString())
                .expiration(Date.from(Instant.now().plus(expireTime, chronoUnit)))
                .signWith(priKey)
                .compact();
    }

    /**
     * 解析Token
     * @param token 令牌
     * @return 解析对象
     */
    public static Jws<Claims> parseToken(String token) {
        Jws<Claims> claimsJws = Jwts.parser().verifyWith(priKey).build().parseSignedClaims(token);

        log.info(claimsJws);
        return claimsJws;
    }

    /**
     * 校验Token
     * @param token 令牌
     * @return 用户Id
     */
    public static String validateToken(String token) {
        Jws<Claims> claimsJws;
        try {
            claimsJws = JWTUtils.parseToken(token);
            log.info(claimsJws.getPayload().toString());
        }catch (ExpiredJwtException e){
            log.error("令牌已经过期，请重新登录");
            throw new ServerServiceException(Errors.SYSTEM_NO_ACCESS_ERROR,"Token已过期，请重新登录");
        }catch (SignatureException e){
            log.error("令牌签名异常，请重新登录");
            throw new ServerServiceException(Errors.SYSTEM_NO_ACCESS_ERROR,"Token签名异常");
        }catch (Exception e){
            log.error(e.getMessage());
            throw new ServerServiceException(Errors.SYSTEM_NO_ACCESS_ERROR,e.getMessage());
        }
        if (!"新区一体化门户".equals(claimsJws.getPayload().getIssuer())) {
            log.error("当前Token签发者为:{}", claimsJws.getPayload().getIssuer());
            throw new ServerServiceException(Errors.SYSTEM_NO_ACCESS_ERROR, "Token签发者有误");
        }
        return claimsJws.getPayload().getSubject();
    }
}


